package com.project.server.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.project.server.dto.OrderDetailRequest;
import com.project.server.dto.OrderRequest;
import com.project.server.exception.BusinessException;
import com.project.server.mapper.*;
import com.project.server.model.*;
import com.project.server.service.OrderService;
import com.project.server.util.JwtUtil;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

import static com.baomidou.mybatisplus.extension.toolkit.Db.updateById;

@Service
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {

    private final OrderMapper orderMapper;
    private final OrderDetailMapper orderDetailMapper;
    private final DishMapper dishMapper;
    private final DiningTableMapper diningTableMapper;
    private final RestaurantMapper restaurantMapper;


    @Override
    @Transactional
    public void create(OrderRequest orderRequest, HttpServletRequest httpRequest) {
        // 获取当前用户ID
        Long userId = JwtUtil.getUserIdFromRequest(httpRequest);

        // 检查餐桌是否可用
        DiningTable table = diningTableMapper.selectById(orderRequest.getTableId());
        if (table == null || table.getStatus() != 0) {
            throw new BusinessException("该餐桌不可预订");
        }
        // 检查该时段该餐厅的该餐桌是否存在冲突,在预约时段的两个时间段
        Long tableId = orderRequest.getTableId();
        Long restaurantId = orderRequest.getRestaurantId();
        LocalDate date = orderRequest.getDate();
        LocalTime time = orderRequest.getTime();
        // 预约时间
        LocalDateTime localDateTime = date.atTime(time);
        // 前两小时
        LocalDateTime startTime = localDateTime.plusHours(-2);
        // 后两小时
        LocalDateTime endTime = localDateTime.plusHours(+2);   // 餐厅餐桌在预定的前后 1小时内不能有其他预约
        if (diningTableMapper.getByReservationTime(startTime,endTime, restaurantId,tableId)) {
            throw new BusinessException("该时间段该餐厅的该餐桌已被预订");
        }

        // 生成订单号
        String orderNo = generateOrderNo();

        // 创建订单
        Order order = new Order();
        BeanUtils.copyProperties(orderRequest, order);
        order.setOrderNo(orderNo);
        order.setUserId(userId);
        order.setStatus(0); // 待确认
        order.setReservationTime(orderRequest.getReservationTime());

        // 先保存订单主信息
        orderMapper.insert(order);

        // 计算订单总金额并保存订单明细
        BigDecimal totalAmount = BigDecimal.ZERO;
        for (OrderDetailRequest detailRequest : orderRequest.getOrderDetails()) {
            // 获取菜品信息
            Dish dish = dishMapper.selectById(detailRequest.getDishId());
            if (dish == null) {
                throw new BusinessException("菜品不存在");
            }

            // 创建订单明细
            OrderDetail detail = new OrderDetail();
            detail.setOrderId(order.getId());
            detail.setDishId(dish.getId());
            detail.setQuantity(detailRequest.getQuantity());
            detail.setPrice(dish.getPrice());
            detail.setSubtotal(dish.getPrice().multiply(new BigDecimal(detailRequest.getQuantity())));

            // 累加总金额
            totalAmount = totalAmount.add(detail.getSubtotal());

            // 保存订单明细
            orderDetailMapper.insert(detail);
        }

        // 更新订单总金额
        order.setTotalAmount(totalAmount);
        orderMapper.updateById(order);

        // 更新餐桌状态
//        table.setStatus(1); // 已占用
//        diningTableMapper.updateById(table);
    }

    @Override
    public List<Order> getMyOrders(HttpServletRequest request,Long status) {
        Long userId = JwtUtil.getUserIdFromRequest(request);
        List<Order> orders = orderMapper.selectList(new LambdaQueryWrapper<Order>()
                .eq(Order::getUserId, userId)
                .eq(status != null,Order::getStatus,status)
                .orderByDesc(Order::getCreateTime));

        // 填充订单明细
        for (Order order : orders) {
            List<OrderDetail> details = orderDetailMapper.selectList(
                new LambdaQueryWrapper<OrderDetail>()
                    .eq(OrderDetail::getOrderId, order.getId())
            );
            // 餐厅名称
            order.setRestaurantName(restaurantMapper.selectById(order.getRestaurantId()).getName());
            order.setTableNumber(diningTableMapper.selectById(order.getTableId()).getTableNumber());


            for (OrderDetail detail : details) {
                Long dishId = detail.getDishId();
                Dish dish = dishMapper.selectById(dishId);
                detail.setDishName(dish.getName());
                detail.setDishImage(dish.getImage());
            }
            order.setOrderDetails(details);
        }

        return orders;
    }

    @Override
    public Order getById(Long id) {
        Order order = orderMapper.selectById(id);
        if (order != null) {
            // 查询订单明细
            List<OrderDetail> details = orderDetailMapper.selectList(
                new LambdaQueryWrapper<OrderDetail>()
                    .eq(OrderDetail::getOrderId, id)
            );
            order.setOrderDetails(details);
            // 餐厅名称
            order.setRestaurantName(restaurantMapper.selectById(order.getRestaurantId()).getName());
            order.setTableNumber(diningTableMapper.selectById(order.getTableId()).getTableNumber());

            for (OrderDetail detail : details) {
                Long dishId = detail.getDishId();
                Dish dish = dishMapper.selectById(dishId);
                detail.setDishName(dish.getName());
                detail.setDishImage(dish.getImage());
            }
        }
        return order;
    }

    @Override
    @Transactional
    public void cancel(Long id, HttpServletRequest request) {
        Long userId = JwtUtil.getUserIdFromRequest(request);

        Order order = orderMapper.selectById(id);
        if (order == null || !order.getUserId().equals(userId)) {
            throw new BusinessException("无权操作");
        }

        if (order.getStatus() != 0 && order.getStatus() != 1) {
            throw new BusinessException("当前状态不可取消");
        }

        // 更新订单状态
        order.setStatus(2); // 已取消
        orderMapper.updateById(order);

        // 释放餐桌
        DiningTable table = diningTableMapper.selectById(order.getTableId());
        if (table != null) {
            table.setStatus(0); // 空闲
            diningTableMapper.updateById(table);
        }
    }

    @Override
    public Page<Order> page(Integer pageNum, Integer pageSize, Long restaurantId, Long userId, Integer status) {
        Page<Order> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();

        if (restaurantId != null) {
            wrapper.eq(Order::getRestaurantId, restaurantId);
        }
        if (userId != null) {
            wrapper.eq(Order::getUserId, userId);
        }
        if (status != null) {
            wrapper.eq(Order::getStatus, status);
        }

        wrapper.orderByDesc(Order::getCreateTime);

        Page<Order> orderPage = orderMapper.selectPage(page, wrapper);
        List<Order> orders = orderPage.getRecords();
        for (Order order : orders) {
            // 餐厅名称
            order.setRestaurantName(restaurantMapper.selectById(order.getRestaurantId()).getName());
            order.setTableNumber(diningTableMapper.selectById(order.getTableId()).getTableNumber());
        }
        return orderPage;
    }

    @Override
    @Transactional
    public void confirm(Long id) {
        Order order = getById(id);
        if (order == null) {
            throw new BusinessException("订单不存在");
        }
        if (order.getStatus() != 0) {
            throw new BusinessException("当前状态不可确认");
        }

        order.setStatus(1);
        updateById(order);
    }

    @Override
    @Transactional
    public void complete(Long id) {
        Order order = getById(id);
        if (order == null) {
            throw new BusinessException("订单不存在");
        }
        if (order.getStatus() != 1) {
            throw new BusinessException("当前状态不可完成");
        }

        order.setStatus(3);
        updateById(order);
    }

    /**
     * 生成订单号
     */
    private String generateOrderNo() {
        return "OD" + DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS")
                .format(LocalDateTime.now());
    }










}
